package com.sikaryofficial.backend.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sikaryofficial.backend.annotation.TenantFilter;
import com.sikaryofficial.backend.constant.BlockTypeEnum;
import com.sikaryofficial.backend.constant.MyStatisticsTypeEnum;
import com.sikaryofficial.backend.constant.RedisCacheKey;
import com.sikaryofficial.backend.constant.ReportBusinessTypeEnum;
import com.sikaryofficial.backend.constant.ReportConstant;
import com.sikaryofficial.backend.constant.StoreSourceEnum;
import com.sikaryofficial.backend.domain.dto.req.content.ContentDeleteReq;
import com.sikaryofficial.backend.domain.dto.req.content.ContentEvaluatePageReq;
import com.sikaryofficial.backend.domain.dto.req.content.ContentPageReq;
import com.sikaryofficial.backend.domain.dto.req.content.ContentProductPageReq;
import com.sikaryofficial.backend.domain.dto.req.content.ContentStorePageReq;
import com.sikaryofficial.backend.domain.dto.resp.BrandTasteEvaluateDTO;
import com.sikaryofficial.backend.domain.dto.resp.EvaluateReplyDTO;
import com.sikaryofficial.backend.domain.dto.resp.StoreListDTO;
import com.sikaryofficial.backend.domain.entity.BrandTaste;
import com.sikaryofficial.backend.domain.entity.BrandTasteEvaluateReply;
import com.sikaryofficial.backend.domain.entity.Store;
import com.sikaryofficial.backend.domain.entity.UserReport;
import com.sikaryofficial.backend.domain.mapping.BrandTasteEvaluateMapping;
import com.sikaryofficial.backend.domain.mapping.BrandTasteMapping;
import com.sikaryofficial.backend.domain.mapping.EvaluateReplyMapping;
import com.sikaryofficial.backend.domain.mapping.StoreMapping;
import com.sikaryofficial.backend.domain.vo.ObjectCount;
import com.sikaryofficial.backend.domain.vo.export.BrandTasteEvaluateExportVO;
import com.sikaryofficial.backend.mapper.UserShieldMapper;
import com.sikaryofficial.backend.service.IBrandTasteEvaluateReplyService;
import com.sikaryofficial.backend.service.IBrandTasteEvaluateService;
import com.sikaryofficial.backend.service.IBrandTasteService;
import com.sikaryofficial.backend.service.IMyStatisticsService;
import com.sikaryofficial.backend.service.IStoreService;
import com.sikaryofficial.backend.service.IUserReportService;
import com.sikaryofficial.backend.service.IUserShieldService;
import com.sikaryofficial.backend.service.address.AddressCacheService;
import com.sikaryofficial.backend.service.article.cache.ArticleCacheService;
import com.sikaryofficial.common.core.exception.ServiceException;
import com.sikaryofficial.common.redis.service.RedisService;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import com.sikaryofficial.system.api.model.AddressDTO;
import com.sikaryofficial.system.api.model.product.BrandTasteDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.sikaryofficial.backend.constant.ArticleConstant.SHIELD_BUSINESS_TYPE_ARTICLE;
import static com.sikaryofficial.backend.constant.ContentConstant.CONTENT_STATUS_REPORT;
import static com.sikaryofficial.backend.constant.ProductConstant.SOURCE_USER_EVALUATE;

/**
 * @author : qinjinyuan
 * @desc : 内容管理服务
 * @date : 2023/10/30 15:39
 */
@Service
@Slf4j
@SuppressWarnings(value = "unchecked")
public class BackendContentManager {
    @Autowired
    private IBrandTasteEvaluateService evaluateService;
    @Autowired
    private IBrandTasteEvaluateReplyService evaluateReplyService;
    @Autowired
    private IStoreService storeService;
    @Autowired
    private IMyStatisticsService myStatisticsService;
    @Autowired
    private IUserReportService reportService;
    @Autowired
    private AddressCacheService addressCacheService;
    @Autowired
    private UserShieldMapper userShieldMapper;
    @Autowired
    private IBrandTasteService brandTasteService;

    @Autowired
    private IUserShieldService userShieldService;
    /**
     * 内容列表-产品
     *
     * @param req
     * @return
     */
    @TenantFilter
    public IPage<BrandTasteDTO> productPage(ContentProductPageReq req) {
        Page<BrandTaste> customerPage = new Page<>(req.getPageNum(), req.getPageSize());
        LambdaQueryWrapper<BrandTaste> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(BrandTaste::getDeletedVersion, 0L)
                .eq(BrandTaste::getSource, SOURCE_USER_EVALUATE)
                .likeRight(CharSequenceUtil.isNotBlank(req.getCreatedName()), BrandTaste::getCreatedName, req.getCreatedName())
                .likeRight(CharSequenceUtil.isNotBlank(req.getProductName()), BrandTaste::getProductName, req.getProductName())
                .eq(CharSequenceUtil.isNotBlank(req.getBrandNo()), BrandTaste::getBrandNo, req.getBrandNo());
        if (Objects.nonNull(req.getStartTime()) && Objects.nonNull(req.getEndTime())) {
            queryWrapper.and(i -> i.between(BrandTaste::getCreatedTime, req.getStartTime(), req.getEndTime()));
        }
        queryWrapper.orderByDesc(BrandTaste::getCreatedTime);
        IPage<BrandTaste> storeIPage = brandTasteService.page(customerPage, queryWrapper);
        if (CollUtil.isEmpty(storeIPage.getRecords())) {
            return new Page<>(req.getPageNum(), req.getPageSize(), 0);
        }
        IPage<BrandTasteDTO> page = storeIPage.convert(BrandTasteMapping.INSTANCE::coverToDTO);
        // 设置序号
        AtomicInteger rowNum = new AtomicInteger(1);
        page.getRecords().forEach(item -> {
            item.setSeqNo((req.getPageNum() - 1) * req.getPageSize() + rowNum.get());
            rowNum.getAndIncrement();
        });
        List<BrandTasteDTO> list = page.getRecords();
        List<Long> brandTasteIds = list.stream().map(BrandTasteDTO::getBrandTasteId).collect(Collectors.toList());
        // 回复数， 点赞数 设值
        buildCountWithProduct(list, brandTasteIds);
        return page;
    }

    /**
     * 内容列表-回复
     *
     * @param req
     * @return
     */
    public IPage<EvaluateReplyDTO> replyPage(ContentPageReq req) {
        Page<BrandTasteEvaluateReply> customerPage = new Page<>(req.getPageNum(), req.getPageSize());
        LambdaQueryWrapper<BrandTasteEvaluateReply> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(BrandTasteEvaluateReply::getEvaluateReplyId, BrandTasteEvaluateReply::getEvaluateId, BrandTasteEvaluateReply::getCreatedTime,
                        BrandTasteEvaluateReply::getCreatedBy, BrandTasteEvaluateReply::getReplyContent, BrandTasteEvaluateReply::getCreatedName
                        , BrandTasteEvaluateReply::getHasBlocked)
                .eq(BrandTasteEvaluateReply::getDeletedVersion, 0L)
                .likeRight(CharSequenceUtil.isNotBlank(req.getCreatedName()), BrandTasteEvaluateReply::getCreatedName, req.getCreatedName())
        ;
        if (Objects.nonNull(req.getStartTime()) && Objects.nonNull(req.getEndTime())) {
            queryWrapper.and(i -> i.between(BrandTasteEvaluateReply::getCreatedTime, req.getStartTime(), req.getEndTime()));
        }
        queryWrapper.orderByDesc(BrandTasteEvaluateReply::getCreatedTime);
        IPage<BrandTasteEvaluateReply> storeIPage = evaluateReplyService.page(customerPage, queryWrapper);
        if (CollUtil.isEmpty(storeIPage.getRecords())) {
            return new Page<>(req.getPageNum(), req.getPageSize(), 0);
        }
        IPage<EvaluateReplyDTO> page = storeIPage.convert(EvaluateReplyMapping.INSTANCE::coverToDTO);
        // 设置序号
        AtomicInteger rowNum = new AtomicInteger(1);
        page.getRecords().forEach(item -> {
            item.setSeqNo((req.getPageNum() - 1) * req.getPageSize() + rowNum.get());
            rowNum.getAndIncrement();
        });
        List<EvaluateReplyDTO> list = page.getRecords();
        List<Long> replyIds = list.stream().map(EvaluateReplyDTO::getEvaluateReplyId).collect(Collectors.toList());
        //  状态 0-正常 1-屏蔽 2-举报
        buildStatusWithEvaluateReply(list, replyIds);
        // 回复数， 点赞数 设值
        buildCountWithEvaluateReply(list, replyIds);
        return page;
    }

    /**
     * 内容列表-店铺
     *
     * @param req
     * @return
     */
    public IPage<StoreListDTO> storePage(ContentStorePageReq req) {
        List<Long> addressIds = Lists.newArrayList();
        req.setAddressIds(addressIds);
        List<AddressDTO> addressDTOList = addressCacheService.getAllAddressByCountry();
        addressIds = addressDTOList.stream().filter(item -> CharSequenceUtil.isNotBlank(req.getCountry()) && item.getCountry().equals(req.getCountry()))
                .filter(item -> CharSequenceUtil.isNotBlank(req.getArea()) && item.getArea().equals(req.getArea()))
                .filter(item -> CharSequenceUtil.isNotBlank(req.getCity()) && item.getCity().equals(req.getCity()))
                .filter(item -> CharSequenceUtil.isNotBlank(req.getCounty()) && item.getCounty().equals(req.getCounty()))
                .map(AddressDTO::getAddressId).collect(Collectors.toList());

        Page<Store> customerPage = new Page<>(req.getPageNum(), req.getPageSize());
        LambdaQueryWrapper<Store> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(Store::getStoreId, Store::getStoreName, Store::getScore, Store::getCreatedTime, Store::getCreatedName, Store::getHasBlocked)
                .eq(Store::getDeletedVersion, 0)
                .eq(Store::getSourceCode, StoreSourceEnum.EVALUATE.getCode())
                .likeRight(CharSequenceUtil.isNotBlank(req.getCreatedName()), Store::getCreatedName, req.getCreatedName())
                .likeRight(CharSequenceUtil.isNotBlank(req.getStoreName()), Store::getStoreName, req.getStoreName())
                .in(CollUtil.isNotEmpty(addressIds), Store::getAddressId, addressIds);
        if (Objects.nonNull(req.getStartTime()) && Objects.nonNull(req.getEndTime())) {
            queryWrapper.and(i -> i.between(Store::getCreatedTime, req.getStartTime(), req.getEndTime()));
        }
        queryWrapper.orderByDesc(Store::getCreatedTime);
        IPage<Store> storePage = storeService.page(customerPage, queryWrapper);
        if (CollUtil.isEmpty(storePage.getRecords())) {
            return new Page<>(req.getPageNum(), req.getPageSize(), 0);
        }
        IPage<StoreListDTO> page = storePage.convert(StoreMapping.INSTANCE::coverDtoToEntity);
        // 设置序号
        AtomicInteger rowNum = new AtomicInteger(1);
        page.getRecords().forEach(item -> {
            item.setSeqNo((req.getPageNum() - 1) * req.getPageSize() + rowNum.get());
            rowNum.getAndIncrement();
        });
        List<StoreListDTO> list = page.getRecords();
        List<Long> storeIds = list.stream().map(StoreListDTO::getStoreId).collect(Collectors.toList());
        //  状态 0-正常 1-屏蔽 2-举报
        buildStatusWithStore(list, storeIds);
        return page;
    }

    /**
     * 评价内容-发布的评价
     *
     * @param req
     * @return
     */
    public IPage<BrandTasteEvaluateDTO> evaluatePage(ContentEvaluatePageReq req) {
        IPage<BrandTasteEvaluateDTO> page = fetchAndProcessEvaluateData(req);
        if (CollUtil.isEmpty(page.getRecords())) {
            return new Page<>(req.getPageNum(), req.getPageSize(), 0);
        }
        return page;
    }

    /**
     * 评价内容-导出
     * @param req
     * @return
     */
    public List<BrandTasteEvaluateExportVO> evaluateExport(ContentEvaluatePageReq req) {
        IPage<BrandTasteEvaluateDTO> page = fetchAndProcessEvaluateData(req);
        if (CollUtil.isEmpty(page.getRecords())) {
            return Collections.emptyList();
        }
        return BrandTasteEvaluateMapping.INSTANCE.coverToExportVOList(page.getRecords());
    }

    private IPage<BrandTasteEvaluateDTO> fetchAndProcessEvaluateData(ContentEvaluatePageReq req) {
        Page<BrandTasteEvaluateDTO> customerPage = new Page<>(req.getPageNum(), req.getPageSize());
        IPage<BrandTasteEvaluateDTO> page = evaluateService.backendContentList(customerPage, req);
        if (CollUtil.isEmpty(page.getRecords())) {
            return page;
        }
        // 设置序号
        AtomicInteger rowNum = new AtomicInteger(1);
        page.getRecords().forEach(item -> {
            item.setSeqNo((req.getPageNum() - 1) * req.getPageSize() + rowNum.get());
            rowNum.getAndIncrement();
        });
        List<BrandTasteEvaluateDTO> list = page.getRecords();
        List<Long> evaluateIds = list.stream().map(BrandTasteEvaluateDTO::getEvaluateId).collect(Collectors.toList());
        // 状态 0-正常 1-屏蔽 2-举报
        buildStatusWithEvaluate(list, evaluateIds);
        // 回复数， 点赞数 设值
        buildCountWithEvaluate(list, evaluateIds);
        return page;
    }

    private void buildCountWithEvaluate(List<BrandTasteEvaluateDTO> list, List<Long> evaluateIds) {
        if (CollUtil.isEmpty(list) || CollUtil.isEmpty(evaluateIds)) {
            return;
        }
        List<ObjectCount> objectCountList = myStatisticsService.countByObjectIds(evaluateIds);
        if (CollUtil.isEmpty(objectCountList)) {
            return;
        }
        Optional.of(objectCountList).ifPresent(objectCounts -> objectCounts.forEach(item -> {
            BrandTasteEvaluateDTO evaluateDTO = list.stream().filter(replyItem -> replyItem.getEvaluateId().equals(item.getObjectId())).findFirst().orElse(null);
            if (Objects.isNull(evaluateDTO)) {
                return;
            }
            if (MyStatisticsTypeEnum.LIKES_PRODUCT_EVALUATE_NUM.getBusinessType().equals(item.getBusinessType())) {
                evaluateDTO.setLikesCount(item.getObjectCount());
            }
            // 去掉回复统计
        }));
    }

    private void buildCountWithEvaluateReply(List<EvaluateReplyDTO> list, List<Long> replyIds) {
        if (CollUtil.isEmpty(list) || CollUtil.isEmpty(replyIds)) {
            return;
        }
        List<ObjectCount> objectCountList = myStatisticsService.countByObjectIds(replyIds);
        if (CollUtil.isEmpty(objectCountList)) {
            return;
        }
        Optional.of(objectCountList).ifPresent(objectCounts -> objectCounts.forEach(item -> {
            EvaluateReplyDTO evaluateReplyDTO = list.stream().filter(replyItem -> replyItem.getEvaluateReplyId().equals(item.getObjectId())).findFirst().orElse(null);
            if (Objects.isNull(evaluateReplyDTO)) {
                return;
            }
            if (MyStatisticsTypeEnum.LIKES_EVALUATE_REPLY_NUM.getBusinessType().equals(item.getBusinessType())) {
                evaluateReplyDTO.setLikesCount(item.getObjectCount());
            }
        }));
    }

    /**
     * 评价、点赞、收藏
     *
     * @param list
     * @param productIds
     */
    private void buildCountWithProduct(List<BrandTasteDTO> list, List<Long> productIds) {
        if (CollUtil.isEmpty(list) || CollUtil.isEmpty(productIds)) {
            return;
        }
        List<ObjectCount> objectCountList = myStatisticsService.countByObjectIds(productIds);
        if (CollUtil.isEmpty(objectCountList)) {
            return;
        }
        Optional.of(objectCountList).ifPresent(objectCounts -> objectCounts.forEach(item -> {
            BrandTasteDTO evaluateDTO = list.stream().filter(replyItem -> replyItem.getBrandTasteId().equals(item.getObjectId())).findFirst().orElse(null);
            if (Objects.isNull(evaluateDTO) || Objects.isNull(item.getBusinessType())) {
                return;
            }
            if (MyStatisticsTypeEnum.LIKES_PRODUCT_NUM.getBusinessType().equals(item.getBusinessType())) {
                evaluateDTO.setLikesCount(item.getObjectCount());
            }
            if (MyStatisticsTypeEnum.COMMENTS_PRODUCT_COUNT.getBusinessType().equals(item.getBusinessType())) {
                evaluateDTO.setEvaluationCount(item.getObjectCount());
            }
            if (MyStatisticsTypeEnum.COLLECTION_PRODUCT_NUM.getBusinessType().equals(item.getBusinessType())) {
                evaluateDTO.setCollectionCount(item.getObjectCount());
            }
        }));
    }

    private void buildStatusWithStore(List<StoreListDTO> list, List<Long> storeIds) {
        // 屏蔽 状态设值  CONTENT_STATUS_SHIELD
        list.forEach(storeItem -> storeItem.setStatus(storeItem.getHasBlocked()));
        // 举报 状态设值  CONTENT_STATUS_REPORT
        List<UserReport> userReports = reportService.list(new LambdaQueryWrapper<UserReport>()
                .eq(UserReport::getBusinessType, ReportConstant.STORE_EVALUATE_TYPE)
                .eq(UserReport::getDeletedVersion, 0)
                .in(UserReport::getRelationId, storeIds)
        );
        if (CollUtil.isNotEmpty(userReports)) {
            userReports.forEach(item -> {
                StoreListDTO evaluateDTO = list.stream().filter(evaluateItem -> evaluateItem.getStoreId().equals(item.getRelationId())).findFirst().orElse(null);
                Optional.ofNullable(evaluateDTO).ifPresent(evaluateDTOItem -> evaluateDTOItem.setStatus(CONTENT_STATUS_REPORT));
            });
        }
    }

    private void buildStatusWithEvaluate(List<BrandTasteEvaluateDTO> list, List<Long> evaluateIds) {
        // 屏蔽 状态设值  CONTENT_STATUS_SHIELD
        list.forEach(evaluateItem -> evaluateItem.setStatus(evaluateItem.getHasBlocked()));
        List<UserReport> userReports = reportService.list(new LambdaQueryWrapper<UserReport>()
                .eq(UserReport::getBusinessType, ReportConstant.EVALUATE_TYPE)
                .eq(UserReport::getDeletedVersion, 0)
                .in(UserReport::getRelationId, evaluateIds)
        );
        // 举报 状态设值  CONTENT_STATUS_REPORT
        if (CollUtil.isNotEmpty(userReports)) {
            userReports.forEach(item -> {
                BrandTasteEvaluateDTO evaluateDTO = list.stream().filter(evaluateItem -> evaluateItem.getEvaluateId().equals(item.getRelationId())).findFirst().orElse(null);
                Optional.ofNullable(evaluateDTO).ifPresent(evaluateDTOItem -> evaluateDTOItem.setStatus(CONTENT_STATUS_REPORT));
            });
        }
    }

    private void buildStatusWithEvaluateReply(List<EvaluateReplyDTO> list, List<Long> replyIds) {
        // 屏蔽 状态设值  CONTENT_STATUS_SHIELD
        list.forEach(replyItem -> replyItem.setStatus(replyItem.getHasBlocked()));
        // 举报 状态设值  CONTENT_STATUS_REPORT
        List<UserReport> userReports = reportService.list(new LambdaQueryWrapper<UserReport>()
                .eq(UserReport::getBusinessType, ReportConstant.EVALUATE_REPLY_TYPE)
                .eq(UserReport::getDeletedVersion, 0)
                .in(UserReport::getRelationId, replyIds)
        );
        if (CollUtil.isNotEmpty(userReports)) {
            userReports.forEach(item -> {
                EvaluateReplyDTO evaluateDTO = list.stream().filter(evaluateItem -> evaluateItem.getEvaluateReplyId().equals(item.getRelationId())).findFirst().orElse(null);
                Optional.ofNullable(evaluateDTO).ifPresent(evaluateDTOItem -> evaluateDTOItem.setStatus(CONTENT_STATUS_REPORT));
            });
        }
    }
    @Autowired
    private RedisService redisService;
    @Resource
    private ArticleCacheService articleCacheService;
    /**
     * 屏蔽(评价、发布的店铺、回复)
     *
     * @param req
     * @return
     */
    public boolean shieldByObjId(ContentDeleteReq req) {
        ReportBusinessTypeEnum reportBusinessTypeEnum = ReportBusinessTypeEnum.getEnum(req.getBusinessType());
        if (Objects.isNull(reportBusinessTypeEnum)) {
            throw new ServiceException("businessType is not exist");
        }
        BlockTypeEnum blockTypeEnum = BlockTypeEnum.getByShieldAction(req.getShieldAction());
        if (Objects.isNull(blockTypeEnum)) {
            throw new ServiceException("ShieldAction is not exist");
        }
        int flag = userShieldMapper.blockedByObjectId(req.getBusinessType(), req.getObjectId(),
                blockTypeEnum.getDbValue(), SecurityUtils.getUserId());

        if (flag > 0) {
            Collection<String> keys ;
            switch (reportBusinessTypeEnum) {
                case STORE:
                    // 对最新的店铺缓存进行清理
                    keys = redisService.keys(RedisCacheKey.HISMK_STORE_EVALUATE_LIST_PREFIX + "*");
                    for (String key : keys) {
                        redisService.deleteObject(key);
                    }
                    break;
                case EVALUATE:
                    // 对最新的店铺缓存进行清理
                    keys = redisService.keys(RedisCacheKey.LATEST_EVALUATE_STYLE_CACHE + "*");
                    for (String key : keys) {
                        redisService.deleteObject(key);
                    }
                    break;
                case ARTICLE:
                    // 对文章缓存进行清理
                    clearConfigCache(SHIELD_BUSINESS_TYPE_ARTICLE);
                    // 加载统计数据缓存
                    articleCacheService.loadArticleStatistics();
                    break;
                default:
                    break;
            }
        }
        return flag > 0;
    }

    public void clearConfigCache(Integer businessType) {
        if (Objects.nonNull(businessType) && SHIELD_BUSINESS_TYPE_ARTICLE.equals(businessType)) {
            articleCacheService.clearCache();
        }
    }


}
